package penguin.masking;

import java.sql.*;
import java.util.*;

/**
 * @author wuxh
 * @version 1.0.0
 */
public class JdbcHandler {

    Connection connection;

    static JdbcHandler newJdbcHandler(String url, String username, String password, String driver) throws Exception {
        Class.forName(driver);
//        DriverManager.setLogWriter(new PrintWriter(System.out));
        Connection connection = DriverManager.getConnection(url, username, password);
        return new JdbcHandler(connection);
    }

    public JdbcHandler(Connection connection) {
        this.connection = connection;
    }

    private Connection connection() throws Exception {
        return connection;
    }

    public String getDb() throws SQLException {
        String catalog = connection.getCatalog();
        return catalog;
    }

    public List<Map<String, Object>> select(String sql, List<Object> params) throws Exception {
        Connection connection = connection();
        try (
                PreparedStatement preparedStatement = connection.prepareStatement(sql);
                ResultSet resultSet = preparedStatement.executeQuery();) {
            ResultSetMetaData metaData = resultSet.getMetaData();
            if (params != null) {
                for (int i = 0; i < params.size(); i++) {
                    Object o = params.get(i);
                    preparedStatement.setObject(i + 1, o);
                }
            }
            int columnCount = metaData.getColumnCount();
            List<Map<String, Object>> rows = new ArrayList<>();
            while (resultSet.next()) {
                Map<String, Object> row = new LinkedHashMap<>();
                for (int i = 1; i <= columnCount; i++) {
                    String columnName = metaData.getColumnLabel(i);
                    Object object = resultSet.getObject(columnName);
                    row.put(columnName, object);
                }
                rows.add(row);
            }
            return rows;
        }
    }

    public List<Map<String, Object>> select(String sql) throws Exception {
        return select(sql, null);
    }

    public int update(String sql, Collection<Object> params) throws Exception {
        Connection connection = connection();
        try (
                PreparedStatement preparedStatement = connection.prepareStatement(sql);) {
            if (params != null) {
                Iterator<Object> iterator = params.iterator();
                int j = 0;
                while (iterator.hasNext()) {
                    preparedStatement.setObject(++j, iterator.next());
                }
            }
            int i = preparedStatement.executeUpdate();
            return i;
        }
    }

    public int executeUpdate(String sql) throws Exception {
        Connection connection = connection();
        try (Statement statement = connection.createStatement();) {
            int i = statement.executeUpdate(sql);
            return i;
        }
    }

    public boolean execute(String sql) throws Exception {
        Connection connection = connection();
        try (Statement statement = connection.createStatement();) {
            boolean i = statement.execute(sql);
            return i;
        }
    }

    public void addBatch(String[] sqls) throws Exception {
        Connection connection = connection();
        try (Statement statement = connection.createStatement();) {
            for (String sql : sqls) {
                statement.addBatch(sql);
            }
            statement.executeBatch();
        }
    }
}
